package com.carltechnology.mahjonggamecaculation.utils;

import android.content.Context;
import android.content.SharedPreferences;

import com.carltechnology.mahjonggamecaculation.base.MyAbstractSubscriber;
import com.carltechnology.mahjonggamecaculation.base.MyApplication;
import com.carltechnology.mahjonggamecaculation.dao.DataManager;
import com.carltechnology.mahjonggamecaculation.mode.IGameData;
import com.carltechnology.mahjonggamecaculation.mode.IGameRuntimeData;
import com.carltechnology.mahjonggamecaculation.mode.impl.GameDataMode;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * Created by WZTCM on 2016/7/15.
 * This class do role in runtime data recovering.
 * To avoid the data losing when the app cracked.
 */
public class RuntimeDataHelper {
    private enum NAME_TABLE {
        TABLE_NAME("RUNTIMEDATA"),
        TABLE_ISSTORED("RUNTIMEEXITS"),
        TABLE_PLAYERS_ID("PLAYERID"),
        TABLE_PLAYERS_NAME("PLAYERNAMES"),
        TABLE_PLAYERS_DATE("PLAYERDATE"),
        TABLE_PLAYERS_PERUNIT("PLAYERPERUNIT");

        private String name;

        NAME_TABLE(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    private volatile boolean bRuntime = false;
    private IRuntimeDataSolution iSolution = null;

    public RuntimeDataHelper(IRuntimeDataSolution iSolution) {
        this.iSolution = iSolution;
    }

    public void setiSolution(IRuntimeDataSolution iSolution) {
        this.iSolution = iSolution;
    }

    // save runtime thing with sharedprefences
    public void saveRuntimeData() {
        final Context context = MyApplication.getContext();
        Observable.create(new Observable.OnSubscribe<Context>() {
            @Override
            public void call(Subscriber<? super Context> subscriber) {
                subscriber.onNext(context);
                subscriber.onCompleted();
            }
        })
                .subscribeOn(Schedulers.computation())
                .observeOn(Schedulers.io())
                .map(new Func1<Context, SharedPreferences.Editor>() {
                    @Override
                    public SharedPreferences.Editor call(Context context) {
                        return context.getSharedPreferences(NAME_TABLE.TABLE_NAME.getName(), Context.MODE_PRIVATE).edit();
                    }
                })
                .subscribe(new MyStoreRuntimeDataSubscriber());


    }

    // save every item into database
    public void insertRuntimeData(IGameRuntimeData mode) {
        DataManager
                .getInstance()
                .getInsertHelper()
                .insetMahjongRuntimeGameData(new MyInsertRuntimeSubscriber(), mode);
    }

    // get runtime data when recovering.
    public void getRuntimeData() {
        final SharedPreferences pref = MyApplication.getContext().getSharedPreferences(NAME_TABLE.TABLE_NAME.getName(), Context.MODE_PRIVATE);
        Observable.create(new Observable.OnSubscribe<SharedPreferences>() {
            @Override
            public void call(Subscriber<? super SharedPreferences> subscriber) {
                subscriber.onNext(pref);
                subscriber.onCompleted();
            }
        })
                .subscribeOn(Schedulers.computation())
                .observeOn(Schedulers.io())
                .filter(new Func1<SharedPreferences, Boolean>() {
                    @Override
                    public Boolean call(SharedPreferences sharedPreferences) {
                        bRuntime = pref.getBoolean(NAME_TABLE.TABLE_ISSTORED.getName(), false);
                        return bRuntime;
                    }
                })
                .subscribe(new MyGetRuntimeDataSubscriber())
        ;

    }

    // judge if it's in runtime
    public boolean isRuntime() {
        return bRuntime;
    }

    // clear data items in sharedpreferences file and database
    public void clearRuntimeData() {
        final Context context = MyApplication.getContext();
        Observable.create(new Observable.OnSubscribe<Context>() {
            @Override
            public void call(Subscriber<? super Context> subscriber) {
                subscriber.onNext(context);
                subscriber.onCompleted();
            }
        })
                .subscribeOn(Schedulers.computation())
                .observeOn(Schedulers.io())
                .map(new Func1<Context, SharedPreferences.Editor>() {
                    @Override
                    public SharedPreferences.Editor call(Context context) {
                        return context.getSharedPreferences(NAME_TABLE.TABLE_NAME.getName(), Context.MODE_PRIVATE).edit();
                    }
                }).subscribe(new MyClearRuntimeSubscriber());
    }


    //*****************************************************************************************
    // they are the recovering doing things.
    private class MyClearRuntimeSubscriber extends MyAbstractSubscriber<SharedPreferences.Editor> {
        @Override
        public void onNext(SharedPreferences.Editor editor) {
            editor.clear();
            editor.putBoolean(NAME_TABLE.TABLE_ISSTORED.getName(), false);
            editor.commit();
            DataManager.getInstance().getModifyHelper().clearRuntimeGameData(new MyAbstractSubscriber<Boolean>() {
                @Override
                public void onNext(Boolean aBoolean) {

                }
            });
        }
    }

    private class MyInsertRuntimeSubscriber extends MyAbstractSubscriber<IGameRuntimeData> {

        @Override
        public void onNext(IGameRuntimeData iGameRuntimeData) {

        }
    }

    private class MyGetRuntimeDataSubscriber extends MyAbstractSubscriber<SharedPreferences> {

        @Override
        public void onNext(SharedPreferences pref) {
            int id = pref.getInt(NAME_TABLE.TABLE_PLAYERS_ID.getName(), -1);
            String[] names = pref.getString(NAME_TABLE.TABLE_PLAYERS_NAME.getName(), "").split("_");
            String date = pref.getString(NAME_TABLE.TABLE_PLAYERS_DATE.getName(), Utils.getInstance().getTodayDate());
            int perunit = pref.getInt(NAME_TABLE.TABLE_PLAYERS_PERUNIT.getName(), 0);
            MyApplication.getPool()
                    .setGameMode(GameDataMode._of(names, date));
            MyApplication.getPool().setPerUnit(perunit);
            if (iSolution != null)
                iSolution.doRuntimeSolution();
        }
    }

    private class MyStoreRuntimeDataSubscriber extends MyAbstractSubscriber<SharedPreferences.Editor> {
        @Override
        public void onNext(SharedPreferences.Editor editor) {
            editor.clear();
            editor.putBoolean(NAME_TABLE.TABLE_ISSTORED.getName(), true);
            IGameData mode = MyApplication.getPool().getGameMode();
            editor.putInt(NAME_TABLE.TABLE_PLAYERS_ID.getName(), mode.getId());
            editor.putString(NAME_TABLE.TABLE_PLAYERS_NAME.getName(), mode.getValue());
            editor.putString(NAME_TABLE.TABLE_PLAYERS_DATE.getName(), mode.getDate());
            editor.putInt(NAME_TABLE.TABLE_PLAYERS_PERUNIT.getName(), MyApplication.getPool().getPerUnit());
            editor.commit();
        }
    }
    //*****************************************************************************************

}
